#!/bin/bash

# 系统维护脚本
# System Maintenance Script

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 配置变量
SCRIPT_VERSION="1.0.0"
PROJECT_NAME="personal-cloud-notes"
PROJECT_DIR="/var/www/$PROJECT_NAME"
LOG_DIR="$PROJECT_DIR/data/logs"
BACKUP_DIR="$PROJECT_DIR/data/backups"
TEMP_DIR="$PROJECT_DIR/data/temp"
MAINTENANCE_LOG="/var/log/${PROJECT_NAME}-maintenance.log"

# 维护配置
LOG_RETENTION_DAYS=7
BACKUP_RETENTION_DAYS=30
TEMP_FILE_RETENTION_HOURS=24
MAX_LOG_SIZE_MB=100
MAX_BACKUP_SIZE_GB=5

# 函数：打印带颜色的消息
print_message() {
    local color=$1
    local message=$2
    echo -e "${color}${message}${NC}"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$MAINTENANCE_LOG"
}

# 函数：打印标题
print_title() {
    local title=$1
    echo
    print_message $CYAN "=================================="
    print_message $CYAN "$title"
    print_message $CYAN "=================================="
}

# 函数：检查是否以root权限运行
check_root() {
    if [ "$EUID" -ne 0 ]; then
        print_message $RED "此脚本需要root权限运行"
        print_message $BLUE "请使用: sudo $0"
        exit 1
    fi
}

# 函数：清理应用日志
cleanup_application_logs() {
    print_message $YELLOW "清理应用日志..."
    
    local cleaned_files=0
    local freed_space=0
    
    if [ -d "$LOG_DIR" ]; then
        # 清理过期的日志文件
        while IFS= read -r -d '' file; do
            if [ -f "$file" ]; then
                local file_size=$(stat -c%s "$file" 2>/dev/null || echo 0)
                rm "$file"
                cleaned_files=$((cleaned_files + 1))
                freed_space=$((freed_space + file_size))
                print_message $BLUE "删除过期日志: $(basename "$file")"
            fi
        done < <(find "$LOG_DIR" -name "*.log" -type f -mtime +$LOG_RETENTION_DAYS -print0 2>/dev/null)
        
        # 压缩大型日志文件
        while IFS= read -r -d '' file; do
            if [ -f "$file" ]; then
                local file_size_mb=$(( $(stat -c%s "$file" 2>/dev/null || echo 0) / 1024 / 1024 ))
                if [ $file_size_mb -gt $MAX_LOG_SIZE_MB ]; then
                    gzip "$file"
                    print_message $BLUE "压缩大型日志: $(basename "$file")"
                fi
            fi
        done < <(find "$LOG_DIR" -name "*.log" -type f -print0 2>/dev/null)
        
        # 清理空日志文件
        find "$LOG_DIR" -name "*.log" -type f -empty -delete 2>/dev/null || true
        
        local freed_mb=$((freed_space / 1024 / 1024))
        print_message $GREEN "应用日志清理完成: 删除 $cleaned_files 个文件，释放 ${freed_mb}MB 空间"
    else
        print_message $YELLOW "应用日志目录不存在，跳过清理"
    fi
}

# 函数：清理系统日志
cleanup_system_logs() {
    print_message $YELLOW "清理系统日志..."
    
    # 清理Nginx日志
    if [ -d "/var/log/nginx" ]; then
        find /var/log/nginx -name "*.log" -type f -mtime +$LOG_RETENTION_DAYS -delete 2>/dev/null || true
        find /var/log/nginx -name "*.log.*.gz" -type f -mtime +$((LOG_RETENTION_DAYS * 2)) -delete 2>/dev/null || true
        print_message $BLUE "Nginx日志清理完成"
    fi
    
    # 清理MySQL日志
    if [ -d "/var/log/mysql" ]; then
        find /var/log/mysql -name "*.log" -type f -mtime +$LOG_RETENTION_DAYS -delete 2>/dev/null || true
        print_message $BLUE "MySQL日志清理完成"
    fi
    
    # 清理PM2日志
    if command -v pm2 >/dev/null 2>&1; then
        sudo -u pm2 pm2 flush 2>/dev/null || true
        print_message $BLUE "PM2日志清理完成"
    fi
    
    # 清理系统日志（谨慎操作）
    if command -v journalctl >/dev/null 2>&1; then
        journalctl --vacuum-time=${LOG_RETENTION_DAYS}d 2>/dev/null || true
        print_message $BLUE "系统日志清理完成"
    fi
    
    print_message $GREEN "系统日志清理完成"
}

# 函数：清理临时文件
cleanup_temp_files() {
    print_message $YELLOW "清理临时文件..."
    
    local cleaned_files=0
    local freed_space=0
    
    # 清理应用临时文件
    if [ -d "$TEMP_DIR" ]; then
        while IFS= read -r -d '' file; do
            if [ -f "$file" ]; then
                local file_size=$(stat -c%s "$file" 2>/dev/null || echo 0)
                rm "$file"
                cleaned_files=$((cleaned_files + 1))
                freed_space=$((freed_space + file_size))
            fi
        done < <(find "$TEMP_DIR" -type f -mmin +$((TEMP_FILE_RETENTION_HOURS * 60)) -print0 2>/dev/null)
        
        # 清理空目录
        find "$TEMP_DIR" -type d -empty -delete 2>/dev/null || true
    fi
    
    # 清理系统临时文件
    if [ -d "/tmp" ]; then
        find /tmp -name "${PROJECT_NAME}-*" -type f -mtime +1 -delete 2>/dev/null || true
    fi
    
    # 清理npm缓存
    if command -v npm >/dev/null 2>&1; then
        npm cache clean --force >/dev/null 2>&1 || true
        print_message $BLUE "npm缓存清理完成"
    fi
    
    local freed_mb=$((freed_space / 1024 / 1024))
    print_message $GREEN "临时文件清理完成: 删除 $cleaned_files 个文件，释放 ${freed_mb}MB 空间"
}

# 函数：清理旧备份
cleanup_old_backups() {
    print_message $YELLOW "清理旧备份文件..."
    
    local cleaned_files=0
    local freed_space=0
    
    if [ -d "$BACKUP_DIR" ]; then
        # 清理过期的数据库备份
        while IFS= read -r -d '' file; do
            if [ -f "$file" ]; then
                local file_size=$(stat -c%s "$file" 2>/dev/null || echo 0)
                rm "$file"
                cleaned_files=$((cleaned_files + 1))
                freed_space=$((freed_space + file_size))
                print_message $BLUE "删除过期备份: $(basename "$file")"
            fi
        done < <(find "$BACKUP_DIR" -name "*.sql" -o -name "*.sql.gz" -type f -mtime +$BACKUP_RETENTION_DAYS -print0 2>/dev/null)
        
        # 清理过期的文件备份
        while IFS= read -r -d '' file; do
            if [ -f "$file" ]; then
                local file_size=$(stat -c%s "$file" 2>/dev/null || echo 0)
                rm "$file"
                cleaned_files=$((cleaned_files + 1))
                freed_space=$((freed_space + file_size))
                print_message $BLUE "删除过期备份: $(basename "$file")"
            fi
        done < <(find "$BACKUP_DIR" -name "*.tar.gz" -type f -mtime +$BACKUP_RETENTION_DAYS -print0 2>/dev/null)
        
        # 检查备份目录总大小
        local total_size_gb=$(du -sg "$BACKUP_DIR" 2>/dev/null | cut -f1 || echo 0)
        if [ $total_size_gb -gt $MAX_BACKUP_SIZE_GB ]; then
            print_message $YELLOW "备份目录过大 (${total_size_gb}GB)，清理最旧的备份..."
            
            # 删除最旧的备份文件直到大小合理
            while [ $total_size_gb -gt $MAX_BACKUP_SIZE_GB ]; do
                local oldest_file=$(find "$BACKUP_DIR" -type f \( -name "*.sql" -o -name "*.sql.gz" -o -name "*.tar.gz" \) -printf '%T+ %p\n' | sort | head -1 | cut -d' ' -f2-)
                if [ -n "$oldest_file" ] && [ -f "$oldest_file" ]; then
                    rm "$oldest_file"
                    print_message $BLUE "删除最旧备份: $(basename "$oldest_file")"
                    total_size_gb=$(du -sg "$BACKUP_DIR" 2>/dev/null | cut -f1 || echo 0)
                else
                    break
                fi
            done
        fi
        
        local freed_gb=$((freed_space / 1024 / 1024 / 1024))
        print_message $GREEN "备份清理完成: 删除 $cleaned_files 个文件，释放 ${freed_gb}GB 空间"
    else
        print_message $YELLOW "备份目录不存在，跳过清理"
    fi
}

# 函数：优化数据库
optimize_database() {
    print_message $YELLOW "优化数据库..."
    
    if [ -f "$PROJECT_DIR/.env" ]; then
        local db_password=$(grep "DB_PASSWORD=" "$PROJECT_DIR/.env" | cut -d'=' -f2)
        local db_user=$(grep "DB_USER=" "$PROJECT_DIR/.env" | cut -d'=' -f2)
        local db_name=$(grep "DB_NAME=" "$PROJECT_DIR/.env" | cut -d'=' -f2)
        
        if mysql -u"$db_user" -p"$db_password" -e "USE $db_name;" >/dev/null 2>&1; then
            # 优化表
            mysql -u"$db_user" -p"$db_password" "$db_name" << EOF
OPTIMIZE TABLE users;
OPTIMIZE TABLE notes;
OPTIMIZE TABLE files;
ANALYZE TABLE users;
ANALYZE TABLE notes;
ANALYZE TABLE files;
EOF
            
            # 清理查询缓存
            mysql -u"$db_user" -p"$db_password" -e "FLUSH QUERY CACHE;" 2>/dev/null || true
            
            print_message $GREEN "数据库优化完成"
        else
            print_message $RED "数据库连接失败，跳过优化"
        fi
    else
        print_message $YELLOW "数据库配置文件未找到，跳过优化"
    fi
}

# 函数：更新系统包
update_system_packages() {
    print_message $YELLOW "更新系统包..."
    
    # 检测操作系统
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        local distro=$ID
    else
        print_message $YELLOW "无法检测操作系统，跳过系统更新"
        return
    fi
    
    case $distro in
        ubuntu|debian)
            apt update >/dev/null 2>&1
            apt list --upgradable 2>/dev/null | grep -v "Listing..." | wc -l | xargs -I {} print_message $BLUE "可更新包数量: {}"
            # 只更新安全补丁（可选）
            # apt upgrade -y >/dev/null 2>&1
            ;;
        centos|rhel|rocky|almalinux)
            yum check-update >/dev/null 2>&1 || true
            yum list updates 2>/dev/null | grep -v "Updated Packages" | wc -l | xargs -I {} print_message $BLUE "可更新包数量: {}"
            # yum update -y >/dev/null 2>&1
            ;;
        fedora)
            dnf check-update >/dev/null 2>&1 || true
            dnf list updates 2>/dev/null | grep -v "Updated Packages" | wc -l | xargs -I {} print_message $BLUE "可更新包数量: {}"
            # dnf update -y >/dev/null 2>&1
            ;;
    esac
    
    print_message $GREEN "系统包检查完成"
}

# 函数：检查磁盘空间
check_disk_space() {
    print_message $YELLOW "检查磁盘空间..."
    
    local usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
    local available=$(df / | awk 'NR==2 {print int($4/1024/1024)}')
    
    print_message $BLUE "根分区使用率: ${usage}%，可用空间: ${available}GB"
    
    if [ "$usage" -gt 90 ]; then
        print_message $RED "⚠️  磁盘空间严重不足！"
        
        # 显示占用空间最大的目录
        print_message $BLUE "占用空间最大的目录:"
        du -h / --max-depth=1 2>/dev/null | sort -hr | head -10 | while read size dir; do
            print_message $YELLOW "  $size  $dir"
        done
        
        return 1
    elif [ "$usage" -gt 80 ]; then
        print_message $YELLOW "⚠️  磁盘空间不足，建议清理"
        return 1
    else
        print_message $GREEN "磁盘空间充足"
        return 0
    fi
}

# 函数：检查服务健康状态
check_service_health() {
    print_message $YELLOW "检查服务健康状态..."
    
    local unhealthy_services=()
    
    # 检查Nginx
    if ! systemctl is-active --quiet nginx; then
        unhealthy_services+=("nginx")
    fi
    
    # 检查MySQL
    if ! systemctl is-active --quiet mysql 2>/dev/null && ! systemctl is-active --quiet mysqld 2>/dev/null; then
        unhealthy_services+=("mysql")
    fi
    
    # 检查PM2应用
    if ! sudo -u pm2 pm2 list 2>/dev/null | grep -q "$PROJECT_NAME.*online"; then
        unhealthy_services+=("pm2-app")
    fi
    
    if [ ${#unhealthy_services[@]} -eq 0 ]; then
        print_message $GREEN "所有服务运行正常"
        return 0
    else
        print_message $RED "发现异常服务: ${unhealthy_services[*]}"
        
        # 尝试重启异常服务
        for service in "${unhealthy_services[@]}"; do
            case $service in
                nginx)
                    print_message $BLUE "尝试重启Nginx..."
                    systemctl restart nginx && print_message $GREEN "Nginx重启成功" || print_message $RED "Nginx重启失败"
                    ;;
                mysql)
                    print_message $BLUE "尝试重启MySQL..."
                    systemctl restart mysql 2>/dev/null || systemctl restart mysqld 2>/dev/null
                    if systemctl is-active --quiet mysql 2>/dev/null || systemctl is-active --quiet mysqld 2>/dev/null; then
                        print_message $GREEN "MySQL重启成功"
                    else
                        print_message $RED "MySQL重启失败"
                    fi
                    ;;
                pm2-app)
                    print_message $BLUE "尝试重启PM2应用..."
                    sudo -u pm2 pm2 restart "$PROJECT_NAME" 2>/dev/null && print_message $GREEN "PM2应用重启成功" || print_message $RED "PM2应用重启失败"
                    ;;
            esac
        done
        
        return 1
    fi
}

# 函数：生成维护报告
generate_maintenance_report() {
    local report_file="/tmp/${PROJECT_NAME}-maintenance-report-$(date +%Y%m%d-%H%M%S).txt"
    
    {
        echo "个人云笔记系统维护报告"
        echo "生成时间: $(date)"
        echo "========================================"
        echo
        
        echo "磁盘使用情况:"
        df -h /
        echo
        
        echo "内存使用情况:"
        free -h
        echo
        
        echo "系统负载:"
        uptime
        echo
        
        echo "服务状态:"
        systemctl status nginx --no-pager -l | head -5
        echo
        systemctl status mysql --no-pager -l 2>/dev/null | head -5 || systemctl status mysqld --no-pager -l | head -5
        echo
        sudo -u pm2 pm2 list 2>/dev/null || echo "PM2状态获取失败"
        echo
        
        echo "日志目录大小:"
        if [ -d "$LOG_DIR" ]; then
            du -sh "$LOG_DIR"
        else
            echo "日志目录不存在"
        fi
        echo
        
        echo "备份目录大小:"
        if [ -d "$BACKUP_DIR" ]; then
            du -sh "$BACKUP_DIR"
        else
            echo "备份目录不存在"
        fi
        echo
        
        echo "最近的错误日志:"
        if [ -f "$LOG_DIR/error.log" ]; then
            tail -10 "$LOG_DIR/error.log"
        else
            echo "错误日志文件不存在"
        fi
        
    } > "$report_file"
    
    print_message $GREEN "维护报告已生成: $report_file"
}

# 函数：发送维护通知
send_maintenance_notification() {
    local status=$1
    local message=$2
    
    # 这里可以集成邮件通知、Slack通知等
    # 目前只记录到日志
    print_message $BLUE "维护通知: $status - $message"
    
    # 示例：发送邮件通知（需要配置邮件服务）
    # if command -v mail >/dev/null 2>&1; then
    #     echo "$message" | mail -s "个人云笔记维护通知 - $status" admin@example.com
    # fi
}

# 函数：显示帮助信息
show_help() {
    echo "个人云笔记系统维护脚本 v$SCRIPT_VERSION"
    echo
    echo "用法: $0 [选项]"
    echo
    echo "选项:"
    echo "  --help, -h           显示帮助信息"
    echo "  --version, -v        显示版本信息"
    echo "  --logs-only          仅清理日志文件"
    echo "  --backups-only       仅清理备份文件"
    echo "  --temp-only          仅清理临时文件"
    echo "  --db-optimize        仅优化数据库"
    echo "  --health-check       仅检查服务健康状态"
    echo "  --report             生成维护报告"
    echo "  --dry-run            预览模式，不执行实际操作"
    echo
    echo "示例:"
    echo "  $0                   # 执行完整维护"
    echo "  $0 --logs-only       # 仅清理日志"
    echo "  $0 --health-check    # 仅检查服务状态"
    echo "  $0 --dry-run         # 预览维护操作"
    echo
}

# 主函数
main() {
    # 处理命令行参数
    local logs_only=false
    local backups_only=false
    local temp_only=false
    local db_optimize_only=false
    local health_check_only=false
    local report_only=false
    local dry_run=false
    
    while [[ $# -gt 0 ]]; do
        case $1 in
            --help|-h)
                show_help
                exit 0
                ;;
            --version|-v)
                echo "个人云笔记维护脚本 v$SCRIPT_VERSION"
                exit 0
                ;;
            --logs-only)
                logs_only=true
                shift
                ;;
            --backups-only)
                backups_only=true
                shift
                ;;
            --temp-only)
                temp_only=true
                shift
                ;;
            --db-optimize)
                db_optimize_only=true
                shift
                ;;
            --health-check)
                health_check_only=true
                shift
                ;;
            --report)
                report_only=true
                shift
                ;;
            --dry-run)
                dry_run=true
                shift
                ;;
            *)
                print_message $RED "未知选项: $1"
                show_help
                exit 1
                ;;
        esac
    done
    
    # 开始维护
    print_title "个人云笔记系统维护 v$SCRIPT_VERSION"
    
    if [ "$dry_run" = true ]; then
        print_message $YELLOW "预览模式 - 不会执行实际操作"
    fi
    
    # 检查权限
    check_root
    
    # 创建维护日志
    touch "$MAINTENANCE_LOG"
    
    local maintenance_start_time=$(date)
    local maintenance_errors=0
    
    # 执行维护任务
    if [ "$report_only" = true ]; then
        generate_maintenance_report
    elif [ "$health_check_only" = true ]; then
        check_service_health || ((maintenance_errors++))
    elif [ "$logs_only" = true ]; then
        cleanup_application_logs || ((maintenance_errors++))
        cleanup_system_logs || ((maintenance_errors++))
    elif [ "$backups_only" = true ]; then
        cleanup_old_backups || ((maintenance_errors++))
    elif [ "$temp_only" = true ]; then
        cleanup_temp_files || ((maintenance_errors++))
    elif [ "$db_optimize_only" = true ]; then
        optimize_database || ((maintenance_errors++))
    else
        # 完整维护流程
        print_message $BLUE "开始完整系统维护..."
        
        # 1. 检查磁盘空间
        check_disk_space || ((maintenance_errors++))
        
        # 2. 清理日志文件
        cleanup_application_logs || ((maintenance_errors++))
        cleanup_system_logs || ((maintenance_errors++))
        
        # 3. 清理临时文件
        cleanup_temp_files || ((maintenance_errors++))
        
        # 4. 清理旧备份
        cleanup_old_backups || ((maintenance_errors++))
        
        # 5. 优化数据库
        optimize_database || ((maintenance_errors++))
        
        # 6. 更新系统包信息
        update_system_packages || ((maintenance_errors++))
        
        # 7. 检查服务健康状态
        check_service_health || ((maintenance_errors++))
        
        # 8. 生成维护报告
        generate_maintenance_report
    fi
    
    # 维护总结
    local maintenance_end_time=$(date)
    print_title "维护总结"
    
    print_message $BLUE "开始时间: $maintenance_start_time"
    print_message $BLUE "结束时间: $maintenance_end_time"
    
    if [ $maintenance_errors -eq 0 ]; then
        print_message $GREEN "✓ 系统维护完成，未发现问题"
        send_maintenance_notification "SUCCESS" "系统维护成功完成"
    else
        print_message $YELLOW "⚠️  系统维护完成，发现 $maintenance_errors 个问题"
        send_maintenance_notification "WARNING" "系统维护完成，但发现 $maintenance_errors 个问题，请检查日志"
    fi
    
    print_message $BLUE "维护日志: $MAINTENANCE_LOG"
    
    exit $maintenance_errors
}

# 错误处理
trap 'print_message $RED "维护过程中发生错误"; exit 1' ERR

# 运行主函数
main "$@"